/**
 * 
 */
package IC.Analyzer.Types;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

public class MethodType extends Type {
	private List<Type> args;
	private Type retType;
	private static Map<List<Type>,MethodType> cache;

	public static MethodType getIt(Type retType, List<Type> args) {
		// create cache
		if (cache == null) cache = new HashMap<List<Type>,MethodType>();

		// build signature for hashing purposes
		List<Type> signature = new ArrayList<Type>();
		signature.add(retType);
		for (Type t : args) { signature.add(t); };

		// check if the signature exists
		MethodType ret = cache.get(signature);
		if (ret == null) { 
			ret = new MethodType(retType, args);
			cache.put(signature,ret);
		}
		return ret;
	}

	private MethodType(Type retType, List<Type> args) {
		this.args = args;
		this.retType = retType;
	}

	/**
	 * @return the args
	 */
	public List<Type> getArgs() {
		return args;
	}

	/**
	 * @return the retType
	 */
	public Type getRetType() {
		return retType;
	}

	public String toString() {
		StringBuffer s = new StringBuffer(retType.toString());
		boolean isFirst = true;

		s.append("(");
		for (Type t: args) {
			if (!isFirst) s.append(",");
			s.append(t.toString());
			isFirst = false;
		}
		s.append(")");
		return s.toString();
	}

	/**
	 * 
	 * @return a string represantation of all method types 
	 */
	public static String toStringAll() {
		StringBuffer s = new StringBuffer();

		Set<Entry<List<Type>, MethodType>> set = cache.entrySet();

		for(Entry<List<Type>, MethodType> e : set) {
			s.append(e.getValue());
			s.append("\n");
		}

		return s.toString();
	}
}
